use alloc::boxed::Box;
use alloc::sync::Arc;
use alloc::vec::Vec;
use core::fmt;
use core::fmt::{Debug, Formatter};
use core::marker::PhantomData;
use core::ops::{Deref, DerefMut};
#[cfg(feature = "std")]
use std::io;

use pki_types::{DnsName, UnixTime};

use super::hs;
use crate::builder::ConfigBuilder;
#[cfg(feature = "std")]
use crate::common_state::Protocol;
use crate::common_state::{CommonState, Side, State};
use crate::conn::{ConnectionCommon, ConnectionCore, UnbufferedConnectionCommon};
#[cfg(doc)]
use crate::crypto;
use crate::crypto::CryptoProvider;
use crate::enums::{CipherSuite, ProtocolVersion, SignatureScheme};
use crate::error::Error;
#[cfg(feature = "logging")]
use crate::log::trace;
use crate::msgs::base::Payload;
use crate::msgs::handshake::{ClientHelloPayload, ProtocolName, ServerExtension};
use crate::msgs::message::Message;
#[cfg(feature = "std")]
use crate::time_provider::DefaultTimeProvider;
use crate::time_provider::TimeProvider;
use crate::vecbuf::ChunkVecBuffer;
#[cfg(feature = "std")]
use crate::WantsVerifier;
use crate::{sign, verify, versions, KeyLog, WantsVersions};

/// A trait for the ability to store server session data.
///
/// The keys and values are opaque.
///
/// Both the keys and values should be treated as
/// **highly sensitive data**, containing enough key material
/// to break all security of the corresponding sessions.
///
/// Implementations can be lossy (in other words, forgetting
/// key/value pairs) without any negative security consequences.
///
/// However, note that `take` **must** reliably delete a returned
/// value.  If it does not, there may be security consequences.
///
/// `put` and `take` are mutating operations; this isn't expressed
/// in the type system to allow implementations freedom in
/// how to achieve interior mutability.  `Mutex` is a common
/// choice.
pub trait StoresServerSessions: Debug + Send + Sync {
    /// Store session secrets encoded in `value` against `key`,
    /// overwrites any existing value against `key`.  Returns `true`
    /// if the value was stored.
    fn put(&self, key: Vec<u8>, value: Vec<u8>) -> bool;

    /// Find a value with the given `key`.  Return it, or None
    /// if it doesn't exist.
    fn get(&self, key: &[u8]) -> Option<Vec<u8>>;

    /// Find a value with the given `key`.  Return it and delete it;
    /// or None if it doesn't exist.
    fn take(&self, key: &[u8]) -> Option<Vec<u8>>;

    /// Whether the store can cache another session. This is used to indicate to clients
    /// whether their session can be resumed; the implementation is not required to remember
    /// a session even if it returns `true` here.
    fn can_cache(&self) -> bool;
}

/// A trait for the ability to encrypt and decrypt tickets.
pub trait ProducesTickets: Debug + Send + Sync {
    /// Returns true if this implementation will encrypt/decrypt
    /// tickets.  Should return false if this is a dummy
    /// implementation: the server will not send the SessionTicket
    /// extension and will not call the other functions.
    fn enabled(&self) -> bool;

    /// Returns the lifetime in seconds of tickets produced now.
    /// The lifetime is provided as a hint to clients that the
    /// ticket will not be useful after the given time.
    ///
    /// This lifetime must be implemented by key rolling and
    /// erasure, *not* by storing a lifetime in the ticket.
    ///
    /// The objective is to limit damage to forward secrecy caused
    /// by tickets, not just limiting their lifetime.
    fn lifetime(&self) -> u32;

    /// Encrypt and authenticate `plain`, returning the resulting
    /// ticket.  Return None if `plain` cannot be encrypted for
    /// some reason: an empty ticket will be sent and the connection
    /// will continue.
    fn encrypt(&self, plain: &[u8]) -> Option<Vec<u8>>;

    /// Decrypt `cipher`, validating its authenticity protection
    /// and recovering the plaintext.  `cipher` is fully attacker
    /// controlled, so this decryption must be side-channel free,
    /// panic-proof, and otherwise bullet-proof.  If the decryption
    /// fails, return None.
    fn decrypt(&self, cipher: &[u8]) -> Option<Vec<u8>>;
}

/// How to choose a certificate chain and signing key for use
/// in server authentication.
///
/// This is suitable when selecting a certificate does not require
/// I/O or when the application is using blocking I/O anyhow.
///
/// For applications that use async I/O and need to do I/O to choose
/// a certificate (for instance, fetching a certificate from a data store),
/// the [`Acceptor`] interface is more suitable.
pub trait ResolvesServerCert: Debug + Send + Sync {
    /// Choose a certificate chain and matching key given simplified
    /// ClientHello information.
    ///
    /// Return `None` to abort the handshake.
    fn resolve(&self, client_hello: ClientHello) -> Option<Arc<sign::CertifiedKey>>;
}

/// A struct representing the received Client Hello
pub struct ClientHello<'a> {
    server_name: &'a Option<DnsName<'a>>,
    signature_schemes: &'a [SignatureScheme],
    alpn: Option<&'a Vec<ProtocolName>>,
    cipher_suites: &'a [CipherSuite],
}

impl<'a> ClientHello<'a> {
    /// Creates a new ClientHello
    pub(super) fn new(
        server_name: &'a Option<DnsName>,
        signature_schemes: &'a [SignatureScheme],
        alpn: Option<&'a Vec<ProtocolName>>,
        cipher_suites: &'a [CipherSuite],
    ) -> Self {
        trace!("sni {:?}", server_name);
        trace!("sig schemes {:?}", signature_schemes);
        trace!("alpn protocols {:?}", alpn);
        trace!("cipher suites {:?}", cipher_suites);

        ClientHello {
            server_name,
            signature_schemes,
            alpn,
            cipher_suites,
        }
    }

    /// Get the server name indicator.
    ///
    /// Returns `None` if the client did not supply a SNI.
    pub fn server_name(&self) -> Option<&str> {
        self.server_name
            .as_ref()
            .map(<DnsName as AsRef<str>>::as_ref)
    }

    /// Get the compatible signature schemes.
    ///
    /// Returns standard-specified default if the client omitted this extension.
    pub fn signature_schemes(&self) -> &[SignatureScheme] {
        self.signature_schemes
    }

    /// Get the ALPN protocol identifiers submitted by the client.
    ///
    /// Returns `None` if the client did not include an ALPN extension.
    ///
    /// Application Layer Protocol Negotiation (ALPN) is a TLS extension that lets a client
    /// submit a set of identifiers that each a represent an application-layer protocol.
    /// The server will then pick its preferred protocol from the set submitted by the client.
    /// Each identifier is represented as a byte array, although common values are often ASCII-encoded.
    /// See the official RFC-7301 specifications at <https://datatracker.ietf.org/doc/html/rfc7301>
    /// for more information on ALPN.
    ///
    /// For example, a HTTP client might specify "http/1.1" and/or "h2". Other well-known values
    /// are listed in the at IANA registry at
    /// <https://www.iana.org/assignments/tls-extensiontype-values/tls-extensiontype-values.xhtml#alpn-protocol-ids>.
    ///
    /// The server can specify supported ALPN protocols by setting [`ServerConfig::alpn_protocols`].
    /// During the handshake, the server will select the first protocol configured that the client supports.
    pub fn alpn(&self) -> Option<impl Iterator<Item = &'a [u8]>> {
        self.alpn.map(|protocols| {
            protocols
                .iter()
                .map(|proto| proto.as_ref())
        })
    }

    /// Get cipher suites.
    pub fn cipher_suites(&self) -> &[CipherSuite] {
        self.cipher_suites
    }
}

/// Common configuration for a set of server sessions.
///
/// Making one of these is cheap, though one of the inputs may be expensive: gathering trust roots
/// from the operating system to add to the [`RootCertStore`] passed to a `ClientCertVerifier`
/// builder may take on the order of a few hundred milliseconds.
///
/// These must be created via the [`ServerConfig::builder()`] or [`ServerConfig::builder_with_provider()`]
/// function.
///
/// # Defaults
///
/// * [`ServerConfig::max_fragment_size`]: the default is `None` (meaning 16kB).
/// * [`ServerConfig::session_storage`]: if the `std` feature is enabled, the default stores 256
///   sessions in memory. If the `std` feature is not enabled, the default is to not store any
///   sessions. In a no-std context, by enabling the `hashbrown` feature you may provide your
///   own `session_storage` using [`ServerSessionMemoryCache`] and a `crate::lock::MakeMutex`
///   implementation.
/// * [`ServerConfig::alpn_protocols`]: the default is empty -- no ALPN protocol is negotiated.
/// * [`ServerConfig::key_log`]: key material is not logged.
/// * [`ServerConfig::send_tls13_tickets`]: 4 tickets are sent.
///
/// [`RootCertStore`]: crate::RootCertStore
/// [`ServerSessionMemoryCache`]: crate::server::handy::ServerSessionMemoryCache
#[derive(Clone, Debug)]
pub struct ServerConfig {
    /// Source of randomness and other crypto.
    pub(super) provider: Arc<CryptoProvider>,

    /// Ignore the client's ciphersuite order. Instead,
    /// choose the top ciphersuite in the server list
    /// which is supported by the client.
    pub ignore_client_order: bool,

    /// The maximum size of plaintext input to be emitted in a single TLS record.
    /// A value of None is equivalent to the [TLS maximum] of 16 kB.
    ///
    /// rustls enforces an arbitrary minimum of 32 bytes for this field.
    /// Out of range values are reported as errors from [ServerConnection::new].
    ///
    /// Setting this value to a little less than the TCP MSS may improve latency
    /// for stream-y workloads.
    ///
    /// [TLS maximum]: https://datatracker.ietf.org/doc/html/rfc8446#section-5.1
    /// [ServerConnection::new]: crate::server::ServerConnection::new
    pub max_fragment_size: Option<usize>,

    /// How to store client sessions.
    pub session_storage: Arc<dyn StoresServerSessions + Send + Sync>,

    /// How to produce tickets.
    pub ticketer: Arc<dyn ProducesTickets>,

    /// How to choose a server cert and key. This is usually set by
    /// [ConfigBuilder::with_single_cert] or [ConfigBuilder::with_cert_resolver].
    /// For async applications, see also [Acceptor].
    pub cert_resolver: Arc<dyn ResolvesServerCert>,

    /// Protocol names we support, most preferred first.
    /// If empty we don't do ALPN at all.
    pub alpn_protocols: Vec<Vec<u8>>,

    /// Supported protocol versions, in no particular order.
    /// The default is all supported versions.
    pub(super) versions: versions::EnabledVersions,

    /// How to verify client certificates.
    pub(super) verifier: Arc<dyn verify::ClientCertVerifier>,

    /// How to output key material for debugging.  The default
    /// does nothing.
    pub key_log: Arc<dyn KeyLog>,

    /// Allows traffic secrets to be extracted after the handshake,
    /// e.g. for kTLS setup.
    pub enable_secret_extraction: bool,

    /// Amount of early data to accept for sessions created by
    /// this config.  Specify 0 to disable early data.  The
    /// default is 0.
    ///
    /// Read the early data via [`ServerConnection::early_data`].
    ///
    /// The units for this are _both_ plaintext bytes, _and_ ciphertext
    /// bytes, depending on whether the server accepts a client's early_data
    /// or not.  It is therefore recommended to include some slop in
    /// this value to account for the unknown amount of ciphertext
    /// expansion in the latter case.
    pub max_early_data_size: u32,

    /// Whether the server should send "0.5RTT" data.  This means the server
    /// sends data after its first flight of handshake messages, without
    /// waiting for the client to complete the handshake.
    ///
    /// This can improve TTFB latency for either server-speaks-first protocols,
    /// or client-speaks-first protocols when paired with "0RTT" data.  This
    /// comes at the cost of a subtle weakening of the normal handshake
    /// integrity guarantees that TLS provides.  Note that the initial
    /// `ClientHello` is indirectly authenticated because it is included
    /// in the transcript used to derive the keys used to encrypt the data.
    ///
    /// This only applies to TLS1.3 connections.  TLS1.2 connections cannot
    /// do this optimisation and this setting is ignored for them.  It is
    /// also ignored for TLS1.3 connections that even attempt client
    /// authentication.
    ///
    /// This defaults to false.  This means the first application data
    /// sent by the server comes after receiving and validating the client's
    /// handshake up to the `Finished` message.  This is the safest option.
    pub send_half_rtt_data: bool,

    /// How many TLS1.3 tickets to send immediately after a successful
    /// handshake.
    ///
    /// Because TLS1.3 tickets are single-use, this allows
    /// a client to perform multiple resumptions.
    ///
    /// The default is 4.
    ///
    /// If this is 0, no tickets are sent and clients will not be able to
    /// do any resumption.
    pub send_tls13_tickets: usize,

    /// If set to `true`, requires the client to support the extended
    /// master secret extraction method defined in [RFC 7627].
    ///
    /// The default is `true` if the "fips" crate feature is enabled,
    /// `false` otherwise.
    ///
    /// It must be set to `true` to meet FIPS requirement mentioned in section
    /// **D.Q Transition of the TLS 1.2 KDF to Support the Extended Master
    /// Secret** from [FIPS 140-3 IG.pdf].
    ///
    /// [RFC 7627]: https://datatracker.ietf.org/doc/html/rfc7627
    /// [FIPS 140-3 IG.pdf]: https://csrc.nist.gov/csrc/media/Projects/cryptographic-module-validation-program/documents/fips%20140-3/FIPS%20140-3%20IG.pdf
    #[cfg(feature = "tls12")]
    pub require_ems: bool,

    /// Provides the current system time
    pub time_provider: Arc<dyn TimeProvider>,
}

impl ServerConfig {
    /// Create a builder for a server configuration with
    /// [the process-default `CryptoProvider`][CryptoProvider#using-the-per-process-default-cryptoprovider]
    /// and safe protocol version defaults.
    ///
    /// For more information, see the [`ConfigBuilder`] documentation.
    #[cfg(feature = "std")]
    pub fn builder() -> ConfigBuilder<Self, WantsVerifier> {
        Self::builder_with_protocol_versions(versions::DEFAULT_VERSIONS)
    }

    /// Create a builder for a server configuration with
    /// [the process-default `CryptoProvider`][CryptoProvider#using-the-per-process-default-cryptoprovider]
    /// and the provided protocol versions.
    ///
    /// Panics if
    /// - the supported versions are not compatible with the provider (eg.
    ///   the combination of ciphersuites supported by the provider and supported
    ///   versions lead to zero cipher suites being usable),
    /// - if a `CryptoProvider` cannot be resolved using a combination of
    ///   the crate features and process default.
    ///
    /// For more information, see the [`ConfigBuilder`] documentation.
    #[cfg(feature = "std")]
    pub fn builder_with_protocol_versions(
        versions: &[&'static versions::SupportedProtocolVersion],
    ) -> ConfigBuilder<Self, WantsVerifier> {
        // Safety assumptions:
        // 1. that the provider has been installed (explicitly or implicitly)
        // 2. that the process-level default provider is usable with the supplied protocol versions.
        Self::builder_with_provider(Arc::clone(
            CryptoProvider::get_default_or_install_from_crate_features(),
        ))
        .with_protocol_versions(versions)
        .unwrap()
    }

    /// Create a builder for a server configuration with a specific [`CryptoProvider`].
    ///
    /// This will use the provider's configured ciphersuites. You must additionally choose
    /// which protocol versions to enable, using `with_protocol_versions` or
    /// `with_safe_default_protocol_versions` and handling the `Result` in case a protocol
    /// version is not supported by the provider's ciphersuites.
    ///
    /// For more information, see the [`ConfigBuilder`] documentation.
    #[cfg(feature = "std")]
    pub fn builder_with_provider(
        provider: Arc<CryptoProvider>,
    ) -> ConfigBuilder<Self, WantsVersions> {
        ConfigBuilder {
            state: WantsVersions {
                provider,
                time_provider: Arc::new(DefaultTimeProvider),
            },
            side: PhantomData,
        }
    }

    /// Create a builder for a server configuration with no default implementation details.
    ///
    /// This API must be used by `no_std` users.
    ///
    /// You must provide a specific [`TimeProvider`].
    ///
    /// You must provide a specific [`CryptoProvider`].
    ///
    /// This will use the provider's configured ciphersuites. You must additionally choose
    /// which protocol versions to enable, using `with_protocol_versions` or
    /// `with_safe_default_protocol_versions` and handling the `Result` in case a protocol
    /// version is not supported by the provider's ciphersuites.
    ///
    /// For more information, see the [`ConfigBuilder`] documentation.
    pub fn builder_with_details(
        provider: Arc<CryptoProvider>,
        time_provider: Arc<dyn TimeProvider>,
    ) -> ConfigBuilder<Self, WantsVersions> {
        ConfigBuilder {
            state: WantsVersions {
                provider,
                time_provider,
            },
            side: PhantomData,
        }
    }

    /// Return `true` if connections made with this `ServerConfig` will
    /// operate in FIPS mode.
    ///
    /// This is different from [`CryptoProvider::fips()`]: [`CryptoProvider::fips()`]
    /// is concerned only with cryptography, whereas this _also_ covers TLS-level
    /// configuration that NIST recommends.
    pub fn fips(&self) -> bool {
        #[cfg(feature = "tls12")]
        {
            self.provider.fips() && self.require_ems
        }

        #[cfg(not(feature = "tls12"))]
        {
            self.provider.fips()
        }
    }

    /// Return the crypto provider used to construct this client configuration.
    pub fn crypto_provider(&self) -> &Arc<CryptoProvider> {
        &self.provider
    }

    /// We support a given TLS version if it's quoted in the configured
    /// versions *and* at least one ciphersuite for this version is
    /// also configured.
    pub(crate) fn supports_version(&self, v: ProtocolVersion) -> bool {
        self.versions.contains(v)
            && self
                .provider
                .cipher_suites
                .iter()
                .any(|cs| cs.version().version == v)
    }

    #[cfg(feature = "std")]
    pub(crate) fn supports_protocol(&self, proto: Protocol) -> bool {
        self.provider
            .cipher_suites
            .iter()
            .any(|cs| cs.usable_for_protocol(proto))
    }

    pub(super) fn current_time(&self) -> Result<UnixTime, Error> {
        self.time_provider
            .current_time()
            .ok_or(Error::FailedToGetCurrentTime)
    }
}

#[cfg(feature = "std")]
mod connection {
    use alloc::boxed::Box;
    use alloc::sync::Arc;
    use alloc::vec::Vec;
    use core::fmt;
    use core::fmt::{Debug, Formatter};
    use core::ops::{Deref, DerefMut};
    use std::io;

    use super::{Accepted, Accepting, EarlyDataState, ServerConfig, ServerConnectionData};
    use crate::common_state::{CommonState, Context, Side};
    use crate::conn::{ConnectionCommon, ConnectionCore};
    use crate::error::Error;
    use crate::server::hs;
    use crate::suites::ExtractedSecrets;
    use crate::vecbuf::ChunkVecBuffer;

    /// Allows reading of early data in resumed TLS1.3 connections.
    ///
    /// "Early data" is also known as "0-RTT data".
    ///
    /// This structure implements [`std::io::Read`].
    pub struct ReadEarlyData<'a> {
        early_data: &'a mut EarlyDataState,
    }

    impl<'a> ReadEarlyData<'a> {
        fn new(early_data: &'a mut EarlyDataState) -> Self {
            ReadEarlyData { early_data }
        }
    }

    impl<'a> io::Read for ReadEarlyData<'a> {
        fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
            self.early_data.read(buf)
        }

        #[cfg(read_buf)]
        fn read_buf(&mut self, cursor: core::io::BorrowedCursor<'_>) -> io::Result<()> {
            self.early_data.read_buf(cursor)
        }
    }

    /// This represents a single TLS server connection.
    ///
    /// Send TLS-protected data to the peer using the `io::Write` trait implementation.
    /// Read data from the peer using the `io::Read` trait implementation.
    pub struct ServerConnection {
        pub(super) inner: ConnectionCommon<ServerConnectionData>,
    }

    impl ServerConnection {
        /// Make a new ServerConnection.  `config` controls how
        /// we behave in the TLS protocol.
        pub fn new(config: Arc<ServerConfig>) -> Result<Self, Error> {
            let mut common = CommonState::new(Side::Server);
            common.set_max_fragment_size(config.max_fragment_size)?;
            common.enable_secret_extraction = config.enable_secret_extraction;
            Ok(Self {
                inner: ConnectionCommon::from(ConnectionCore::for_server(config, Vec::new())?),
            })
        }

        /// Retrieves the server name, if any, used to select the certificate and
        /// private key.
        ///
        /// This returns `None` until some time after the client's server name indication
        /// (SNI) extension value is processed during the handshake. It will never be
        /// `None` when the connection is ready to send or process application data,
        /// unless the client does not support SNI.
        ///
        /// This is useful for application protocols that need to enforce that the
        /// server name matches an application layer protocol hostname. For
        /// example, HTTP/1.1 servers commonly expect the `Host:` header field of
        /// every request on a connection to match the hostname in the SNI extension
        /// when the client provides the SNI extension.
        ///
        /// The server name is also used to match sessions during session resumption.
        pub fn server_name(&self) -> Option<&str> {
            self.inner.core.get_sni_str()
        }

        /// Application-controlled portion of the resumption ticket supplied by the client, if any.
        ///
        /// Recovered from the prior session's `set_resumption_data`. Integrity is guaranteed by rustls.
        ///
        /// Returns `Some` iff a valid resumption ticket has been received from the client.
        pub fn received_resumption_data(&self) -> Option<&[u8]> {
            self.inner
                .core
                .data
                .received_resumption_data
                .as_ref()
                .map(|x| &x[..])
        }

        /// Set the resumption data to embed in future resumption tickets supplied to the client.
        ///
        /// Defaults to the empty byte string. Must be less than 2^15 bytes to allow room for other
        /// data. Should be called while `is_handshaking` returns true to ensure all transmitted
        /// resumption tickets are affected.
        ///
        /// Integrity will be assured by rustls, but the data will be visible to the client. If secrecy
        /// from the client is desired, encrypt the data separately.
        pub fn set_resumption_data(&mut self, data: &[u8]) {
            assert!(data.len() < 2usize.pow(15));
            self.inner.core.data.resumption_data = data.into();
        }

        /// Explicitly discard early data, notifying the client
        ///
        /// Useful if invariants encoded in `received_resumption_data()` cannot be respected.
        ///
        /// Must be called while `is_handshaking` is true.
        pub fn reject_early_data(&mut self) {
            self.inner.core.reject_early_data()
        }

        /// Returns an `io::Read` implementer you can read bytes from that are
        /// received from a client as TLS1.3 0RTT/"early" data, during the handshake.
        ///
        /// This returns `None` in many circumstances, such as :
        ///
        /// - Early data is disabled if [`ServerConfig::max_early_data_size`] is zero (the default).
        /// - The session negotiated with the client is not TLS1.3.
        /// - The client just doesn't support early data.
        /// - The connection doesn't resume an existing session.
        /// - The client hasn't sent a full ClientHello yet.
        pub fn early_data(&mut self) -> Option<ReadEarlyData> {
            let data = &mut self.inner.core.data;
            if data.early_data.was_accepted() {
                Some(ReadEarlyData::new(&mut data.early_data))
            } else {
                None
            }
        }

        /// Extract secrets, so they can be used when configuring kTLS, for example.
        /// Should be used with care as it exposes secret key material.
        pub fn dangerous_extract_secrets(self) -> Result<ExtractedSecrets, Error> {
            self.inner.dangerous_extract_secrets()
        }
    }

    impl Debug for ServerConnection {
        fn fmt(&self, f: &mut Formatter) -> fmt::Result {
            f.debug_struct("ServerConnection")
                .finish()
        }
    }

    impl Deref for ServerConnection {
        type Target = ConnectionCommon<ServerConnectionData>;

        fn deref(&self) -> &Self::Target {
            &self.inner
        }
    }

    impl DerefMut for ServerConnection {
        fn deref_mut(&mut self) -> &mut Self::Target {
            &mut self.inner
        }
    }

    impl From<ServerConnection> for crate::Connection {
        fn from(conn: ServerConnection) -> Self {
            Self::Server(conn)
        }
    }

    /// Handle a server-side connection before configuration is available.
    ///
    /// `Acceptor` allows the caller to choose a [`ServerConfig`] after reading
    /// the [`super::ClientHello`] of an incoming connection. This is useful for servers
    /// that choose different certificates or cipher suites based on the
    /// characteristics of the `ClientHello`. In particular it is useful for
    /// servers that need to do some I/O to load a certificate and its private key
    /// and don't want to use the blocking interface provided by
    /// [`super::ResolvesServerCert`].
    ///
    /// Create an Acceptor with [`Acceptor::default()`].
    ///
    /// # Example
    ///
    /// ```no_run
    /// # #[cfg(feature = "aws_lc_rs")] {
    /// # fn choose_server_config(
    /// #     _: rustls::server::ClientHello,
    /// # ) -> std::sync::Arc<rustls::ServerConfig> {
    /// #     unimplemented!();
    /// # }
    /// # #[allow(unused_variables)]
    /// # fn main() {
    /// use rustls::server::{Acceptor, ServerConfig};
    /// let listener = std::net::TcpListener::bind("127.0.0.1:0").unwrap();
    /// for stream in listener.incoming() {
    ///     let mut stream = stream.unwrap();
    ///     let mut acceptor = Acceptor::default();
    ///     let accepted = loop {
    ///         acceptor.read_tls(&mut stream).unwrap();
    ///         if let Some(accepted) = acceptor.accept().unwrap() {
    ///             break accepted;
    ///         }
    ///     };
    ///
    ///     // For some user-defined choose_server_config:
    ///     let config = choose_server_config(accepted.client_hello());
    ///     let conn = accepted
    ///         .into_connection(config)
    ///         .unwrap();

    ///     // Proceed with handling the ServerConnection.
    /// }
    /// # }
    /// # }
    /// ```
    pub struct Acceptor {
        inner: Option<ConnectionCommon<ServerConnectionData>>,
    }

    impl Default for Acceptor {
        /// Return an empty Acceptor, ready to receive bytes from a new client connection.
        fn default() -> Self {
            Self {
                inner: Some(
                    ConnectionCore::new(
                        Box::new(Accepting),
                        ServerConnectionData::default(),
                        CommonState::new(Side::Server),
                    )
                    .into(),
                ),
            }
        }
    }

    impl Acceptor {
        /// Read TLS content from `rd`.
        ///
        /// Returns an error if this `Acceptor` has already yielded an [`Accepted`]. For more details,
        /// refer to [`Connection::read_tls()`].
        ///
        /// [`Connection::read_tls()`]: crate::Connection::read_tls
        pub fn read_tls(&mut self, rd: &mut dyn io::Read) -> Result<usize, io::Error> {
            match &mut self.inner {
                Some(conn) => conn.read_tls(rd),
                None => Err(io::Error::new(
                    io::ErrorKind::Other,
                    "acceptor cannot read after successful acceptance",
                )),
            }
        }

        /// Check if a `ClientHello` message has been received.
        ///
        /// Returns `Ok(None)` if the complete `ClientHello` has not yet been received.
        /// Do more I/O and then call this function again.
        ///
        /// Returns `Ok(Some(accepted))` if the connection has been accepted. Call
        /// `accepted.into_connection()` to continue. Do not call this function again.
        ///
        /// Returns `Err((err, alert))` if an error occurred. If an alert is returned, the
        /// application should call `alert.write()` to send the alert to the client. It should
        /// not call `accept()` again.
        pub fn accept(&mut self) -> Result<Option<Accepted>, (Error, AcceptedAlert)> {
            let mut connection = match self.inner.take() {
                Some(conn) => conn,
                None => {
                    return Err((
                        Error::General("Acceptor polled after completion".into()),
                        AcceptedAlert::empty(),
                    ));
                }
            };

            let message = match connection.first_handshake_message() {
                Ok(Some(msg)) => msg,
                Ok(None) => {
                    self.inner = Some(connection);
                    return Ok(None);
                }
                Err(err) => return Err((err, AcceptedAlert::from(connection))),
            };

            let mut cx = Context::from(&mut connection);
            let sig_schemes = match hs::process_client_hello(&message, false, &mut cx) {
                Ok((_, sig_schemes)) => sig_schemes,
                Err(err) => {
                    return Err((err, AcceptedAlert::from(connection)));
                }
            };

            Ok(Some(Accepted {
                connection,
                message,
                sig_schemes,
            }))
        }
    }

    /// Represents a TLS alert resulting from handling the client's `ClientHello` message.
    ///
    /// When [`Acceptor::accept()`] returns an error, it yields an `AcceptedAlert` such that the
    /// application can communicate failure to the client via [`AcceptedAlert::write()`].
    pub struct AcceptedAlert(ChunkVecBuffer);

    impl AcceptedAlert {
        pub(super) fn empty() -> Self {
            Self(ChunkVecBuffer::new(None))
        }

        /// Send the alert to the client.
        ///
        /// To account for short writes this function should be called repeatedly until it
        /// returns `Ok(0)` or an error.
        pub fn write(&mut self, wr: &mut dyn io::Write) -> Result<usize, io::Error> {
            self.0.write_to(wr)
        }

        /// Send the alert to the client.
        ///
        /// This function will invoke the writer until the buffer is empty.
        pub fn write_all(&mut self, wr: &mut dyn io::Write) -> Result<(), io::Error> {
            while self.write(wr)? != 0 {}
            Ok(())
        }
    }

    impl From<ConnectionCommon<ServerConnectionData>> for AcceptedAlert {
        fn from(conn: ConnectionCommon<ServerConnectionData>) -> Self {
            Self(conn.core.common_state.sendable_tls)
        }
    }

    impl Debug for AcceptedAlert {
        fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
            f.debug_struct("AcceptedAlert").finish()
        }
    }
}

#[cfg(feature = "std")]
pub use connection::{AcceptedAlert, Acceptor, ReadEarlyData, ServerConnection};

/// Unbuffered version of `ServerConnection`
///
/// See the [`crate::unbuffered`] module docs for more details
pub struct UnbufferedServerConnection {
    inner: UnbufferedConnectionCommon<ServerConnectionData>,
}

impl UnbufferedServerConnection {
    /// Make a new ServerConnection. `config` controls how we behave in the TLS protocol.
    pub fn new(config: Arc<ServerConfig>) -> Result<Self, Error> {
        let mut common = CommonState::new(Side::Server);
        common.set_max_fragment_size(config.max_fragment_size)?;
        common.enable_secret_extraction = config.enable_secret_extraction;
        Ok(Self {
            inner: UnbufferedConnectionCommon::from(ConnectionCore::for_server(
                config,
                Vec::new(),
            )?),
        })
    }
}

impl Deref for UnbufferedServerConnection {
    type Target = UnbufferedConnectionCommon<ServerConnectionData>;

    fn deref(&self) -> &Self::Target {
        &self.inner
    }
}

impl DerefMut for UnbufferedServerConnection {
    fn deref_mut(&mut self) -> &mut Self::Target {
        &mut self.inner
    }
}

impl UnbufferedConnectionCommon<ServerConnectionData> {
    pub(crate) fn pop_early_data(&mut self) -> Option<Vec<u8>> {
        self.core.data.early_data.pop()
    }
}

/// Represents a `ClientHello` message received through the [`Acceptor`].
///
/// Contains the state required to resume the connection through [`Accepted::into_connection()`].
pub struct Accepted {
    connection: ConnectionCommon<ServerConnectionData>,
    message: Message<'static>,
    sig_schemes: Vec<SignatureScheme>,
}

impl Accepted {
    /// Get the [`ClientHello`] for this connection.
    pub fn client_hello(&self) -> ClientHello<'_> {
        let payload = Self::client_hello_payload(&self.message);
        ClientHello::new(
            &self.connection.core.data.sni,
            &self.sig_schemes,
            payload.alpn_extension(),
            &payload.cipher_suites,
        )
    }

    /// Convert the [`Accepted`] into a [`ServerConnection`].
    ///
    /// Takes the state returned from [`Acceptor::accept()`] as well as the [`ServerConfig`] and
    /// [`sign::CertifiedKey`] that should be used for the session. Returns an error if
    /// configuration-dependent validation of the received `ClientHello` message fails.
    #[cfg(feature = "std")]
    pub fn into_connection(
        mut self,
        config: Arc<ServerConfig>,
    ) -> Result<ServerConnection, (Error, AcceptedAlert)> {
        if let Err(err) = self
            .connection
            .set_max_fragment_size(config.max_fragment_size)
        {
            // We have a connection here, but it won't contain an alert since the error
            // is with the fragment size configured in the `ServerConfig`.
            return Err((err, AcceptedAlert::empty()));
        }

        self.connection.enable_secret_extraction = config.enable_secret_extraction;

        let state = hs::ExpectClientHello::new(config, Vec::new());
        let mut cx = hs::ServerContext::from(&mut self.connection);

        let ch = Self::client_hello_payload(&self.message);
        let new = match state.with_certified_key(self.sig_schemes, ch, &self.message, &mut cx) {
            Ok(new) => new,
            Err(err) => return Err((err, AcceptedAlert::from(self.connection))),
        };

        self.connection.replace_state(new);
        Ok(ServerConnection {
            inner: self.connection,
        })
    }

    fn client_hello_payload<'a>(message: &'a Message) -> &'a ClientHelloPayload {
        match &message.payload {
            crate::msgs::message::MessagePayload::Handshake { parsed, .. } => match &parsed.payload
            {
                crate::msgs::handshake::HandshakePayload::ClientHello(ch) => ch,
                _ => unreachable!(),
            },
            _ => unreachable!(),
        }
    }
}

impl Debug for Accepted {
    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
        f.debug_struct("Accepted").finish()
    }
}

struct Accepting;

impl State<ServerConnectionData> for Accepting {
    fn handle<'m>(
        self: Box<Self>,
        _cx: &mut hs::ServerContext<'_>,
        _m: Message<'m>,
    ) -> Result<Box<dyn State<ServerConnectionData> + 'm>, Error>
    where
        Self: 'm,
    {
        Err(Error::General("unreachable state".into()))
    }

    fn into_owned(self: Box<Self>) -> hs::NextState<'static> {
        self
    }
}

pub(super) enum EarlyDataState {
    New,
    Accepted(ChunkVecBuffer),
    Rejected,
}

impl Default for EarlyDataState {
    fn default() -> Self {
        Self::New
    }
}

impl EarlyDataState {
    pub(super) fn reject(&mut self) {
        *self = Self::Rejected;
    }

    pub(super) fn accept(&mut self, max_size: usize) {
        *self = Self::Accepted(ChunkVecBuffer::new(Some(max_size)));
    }

    #[cfg(feature = "std")]
    fn was_accepted(&self) -> bool {
        matches!(self, Self::Accepted(_))
    }

    pub(super) fn was_rejected(&self) -> bool {
        matches!(self, Self::Rejected)
    }

    fn pop(&mut self) -> Option<Vec<u8>> {
        match self {
            Self::Accepted(ref mut received) => received.pop(),
            _ => None,
        }
    }

    #[cfg(feature = "std")]
    fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
        match self {
            Self::Accepted(ref mut received) => received.read(buf),
            _ => Err(io::Error::from(io::ErrorKind::BrokenPipe)),
        }
    }

    #[cfg(read_buf)]
    fn read_buf(&mut self, cursor: core::io::BorrowedCursor<'_>) -> io::Result<()> {
        match self {
            Self::Accepted(ref mut received) => received.read_buf(cursor),
            _ => Err(io::Error::from(io::ErrorKind::BrokenPipe)),
        }
    }

    pub(super) fn take_received_plaintext(&mut self, bytes: Payload) -> bool {
        let available = bytes.bytes().len();
        match self {
            Self::Accepted(ref mut received) if received.apply_limit(available) == available => {
                received.append(bytes.into_vec());
                true
            }
            _ => false,
        }
    }
}

impl Debug for EarlyDataState {
    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
        match self {
            Self::New => write!(f, "EarlyDataState::New"),
            Self::Accepted(buf) => write!(f, "EarlyDataState::Accepted({})", buf.len()),
            Self::Rejected => write!(f, "EarlyDataState::Rejected"),
        }
    }
}

impl ConnectionCore<ServerConnectionData> {
    pub(crate) fn for_server(
        config: Arc<ServerConfig>,
        extra_exts: Vec<ServerExtension>,
    ) -> Result<Self, Error> {
        let mut common = CommonState::new(Side::Server);
        common.set_max_fragment_size(config.max_fragment_size)?;
        common.enable_secret_extraction = config.enable_secret_extraction;
        Ok(Self::new(
            Box::new(hs::ExpectClientHello::new(config, extra_exts)),
            ServerConnectionData::default(),
            common,
        ))
    }

    #[cfg(feature = "std")]
    pub(crate) fn reject_early_data(&mut self) {
        assert!(
            self.common_state.is_handshaking(),
            "cannot retroactively reject early data"
        );
        self.data.early_data.reject();
    }

    #[cfg(feature = "std")]
    pub(crate) fn get_sni_str(&self) -> Option<&str> {
        self.data.get_sni_str()
    }
}

/// State associated with a server connection.
#[derive(Default, Debug)]
pub struct ServerConnectionData {
    pub(super) sni: Option<DnsName<'static>>,
    pub(super) received_resumption_data: Option<Vec<u8>>,
    pub(super) resumption_data: Vec<u8>,
    pub(super) early_data: EarlyDataState,
}

impl ServerConnectionData {
    #[cfg(feature = "std")]
    pub(super) fn get_sni_str(&self) -> Option<&str> {
        self.sni.as_ref().map(AsRef::as_ref)
    }
}

impl crate::conn::SideData for ServerConnectionData {}

#[cfg(feature = "std")]
#[cfg(test)]
mod tests {
    use std::format;

    use super::*;

    // these branches not reachable externally, unless something else goes wrong.
    #[test]
    fn test_read_in_new_state() {
        assert_eq!(
            format!("{:?}", EarlyDataState::default().read(&mut [0u8; 5])),
            "Err(Kind(BrokenPipe))"
        );
    }

    #[cfg(read_buf)]
    #[test]
    fn test_read_buf_in_new_state() {
        use core::io::BorrowedBuf;

        let mut buf = [0u8; 5];
        let mut buf: BorrowedBuf<'_> = buf.as_mut_slice().into();
        assert_eq!(
            format!("{:?}", EarlyDataState::default().read_buf(buf.unfilled())),
            "Err(Kind(BrokenPipe))"
        );
    }
}
